import { cloud, CloudDB, CloudDBCollection, CloudDBZoneQuery } from '@hw-agconnect/cloud-server';

export class DBUtil {
  private static ZONENAME: string = "YaoBox";

  /**
   * 添加数据
   * @param data
   * @returns
   */
  public static async AddAsync<T>(data: T): Promise<number> {
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    let result = await db
      .collection(data.constructor as { new(): T })
      .insert(data)
    return result;
  }

  /**
   * 查询指定类别相同数据，并返回类别集合
   * @param clazz
   * @param fieldName
   * @param value
   * @returns
   */
  public static async QueryEqualToAsync<T>(clazz: (new () => T) | string, fieldName: string, value: any): Promise<T[]> {
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    let result: T[] = await db
      .collection(clazz)
      .query()
      .equalTo(fieldName, value)
      .get();
    return result;
  }


  /**
   * 查询指定类别相同数据，并返回类别集合,如果集合长度为0，自动添加
   * @param clazz
   * @param fieldName
   * @param value
   * @param addFunc
   * @returns
   */
  public static async QueryEqualToAndAddAsync<T>(clazz: (new () => T) | string, fieldName: string, value: any,
    addFunc: () => T): Promise<T[]> {
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    let result: T[] = await db
      .collection(clazz)
      .query()
      .equalTo(fieldName, value)
      .get();
    if (result.length == 0) {
      let addValue: T = addFunc();
      await this.AddAsync(addValue);
      result = await this.QueryEqualToAsync(clazz, fieldName, value)
    }
    return result;
  }

  /**
   * 查询对应类型的实体类
   * @param clazz
   * @param fieldName
   * @param values
   * @returns
   */
  public static async QueryInAsync<T>(clazz: (new () => T) | string, fieldName: string, values: any[]): Promise<T[]> {
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    let result: T[] = await db
      .collection(clazz)
      .query()
      .in(fieldName, values)
      .get();
    return result;
  }

  /**
   * 查询
   * @param clazz
   * @param func
   * @returns
   */
  public static async QueryAsync<T>(clazz: (new () => T) | string,
    func?: (query: CloudDBZoneQuery<T>) => Promise<CloudDBZoneQuery<T>>): Promise<T[]> {
    let result: T[] = [];
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    let queryCol: CloudDBZoneQuery<T> = await db
      .collection(clazz)
      .query()
    if (func != undefined) {
      queryCol = await func(queryCol);
    }
    result = await queryCol.get();
    return result;
  }

  /**
   * 更新
   * @param clazz
   * @param updateDatas
   * @returns
   */
  public static async UpdateAsync<T>(clazz: (new () => T) | string, updateDatas: T[]): Promise<number> {
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    return await db.collection(clazz)
      .upsert(updateDatas)
  }

  public static async DeleteAsync<T>(clazz: (new () => T) | string, deleteDatas: T[]): Promise<number> {
    const db: CloudDB = cloud.database({ zoneName: this.ZONENAME });
    return await db.collection(clazz)
      .delete(deleteDatas)
  }
}